home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 SRC / Modules / signalmodule.c < prev    next >
Text File  |  1995-12-21  |  12KB  |  488 lines

  1. /***********************************************************
  2. Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
  3. The Netherlands.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Stichting Mathematisch
  12. Centrum or CWI not be used in advertising or publicity pertaining to
  13. distribution of the software without specific, written prior permission.
  14.  
  15. STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
  16. THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
  18. FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  20. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  21. OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  
  23. ******************************************************************/
  24.  
  25. /* Signal module -- many thanks to Lance Ellinghaus */
  26.  
  27. #include "Python.h"
  28. #include "intrcheck.h"
  29.  
  30. #include <signal.h>
  31.  
  32. #ifndef SIG_ERR
  33. #define SIG_ERR ((RETSIGTYPE (*)())-1)
  34. #endif
  35.  
  36. #ifndef NSIG
  37. #define NSIG (_SIGMAX + 1)    /* For QNX */
  38. #endif
  39.  
  40.  
  41. /*
  42.    NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS
  43.  
  44.    When threads are supported, we want the following semantics:
  45.  
  46.    - only the main thread can set a signal handler
  47.    - any thread can get a signal handler
  48.    - signals are only delivered to the main thread
  49.  
  50.    I.e. we don't support "synchronous signals" like SIGFPE (catching
  51.    this doesn't make much sense in Python anyway) nor do we support
  52.    signals as a means of inter-thread communication, since not all
  53.    thread implementations support that (at least our thread library
  54.    doesn't).
  55.  
  56.    We still have the problem that in some implementations signals
  57.    generated by the keyboard (e.g. SIGINT) are delivered to all
  58.    threads (e.g. SGI), while in others (e.g. Solaris) such signals are
  59.    delivered to one random thread (an intermediate possibility would
  60.    be to deliver it to the main thread -- POSIX?).  For now, we have
  61.    a working implementation that works in all three cases -- the
  62.    handler ignores signals if getpid() isn't the same as in the main
  63.    thread.  XXX This is a hack.
  64.  
  65. */
  66.  
  67. #ifdef WITH_THREAD
  68. #include "thread.h"
  69. static long main_thread;
  70. static pid_t main_pid;
  71. #endif
  72.  
  73. struct PySignal_SignalArrayStruct {
  74.     int    tripped;
  75.     PyObject *func;
  76. };
  77.  
  78. static struct PySignal_SignalArrayStruct PySignal_SignalHandlerArray[NSIG];
  79. static int PySignal_IsTripped = 0; /* Speed up sigcheck() when none tripped */
  80.  
  81. static PyObject *PySignal_SignalDefaultHandler;
  82. static PyObject *PySignal_SignalIgnoreHandler;
  83. static PyObject *PySignal_DefaultIntHandler;
  84.  
  85. static PyObject *
  86. PySignal_CDefaultIntHandler(self, arg)
  87.     PyObject *self;
  88.     PyObject *arg;
  89. {
  90.     PyErr_SetNone(PyExc_KeyboardInterrupt);
  91.     return (PyObject *)NULL;
  92. }
  93.  
  94. void
  95. PyErr_SetInterrupt()
  96. {
  97.     PySignal_IsTripped++;
  98.     PySignal_SignalHandlerArray[SIGINT].tripped = 1;
  99. }
  100.  
  101. static RETSIGTYPE
  102. PySignal_Handler(sig_num)
  103.     int sig_num;
  104. {
  105. #ifdef WITH_THREAD
  106.     /* See NOTES section above */
  107.     if (getpid() == main_pid) {
  108. #endif
  109.         PySignal_IsTripped++;
  110.         PySignal_SignalHandlerArray[sig_num].tripped = 1;
  111. #ifdef WITH_THREAD
  112.     }
  113. #endif
  114. #ifdef SIGCHLD
  115.     if (sig_num == SIGCHLD) {
  116.         /* To avoid infinite recursion, this signal remains
  117.            reset until explicit re-instated.
  118.            Don't clear the 'func' field as it is our pointer
  119.            to the Python handler... */
  120.         return;
  121.     }
  122. #endif
  123.     (void *)signal(sig_num, &PySignal_Handler);
  124. }
  125.  
  126.  
  127. #ifndef DONT_HAVE_SIG_ALARM
  128. static PyObject *
  129. PySignal_Alarm(self, args)
  130.     PyObject *self; /* Not used */
  131.     PyObject *args;
  132. {
  133.     int t;
  134.     if (!PyArg_Parse(args, "i", &t))
  135.         return (PyObject *)NULL;
  136.     /* alarm() returns the number of seconds remaining */
  137.     return PyInt_FromLong(alarm(t));
  138. }
  139. #endif
  140.  
  141. #ifndef DONT_HAVE_SIG_PAUSE
  142. static PyObject *
  143. PySignal_Pause(self, args)
  144.     PyObject *self; /* Not used */
  145.     PyObject *args;
  146. {
  147.     if (!PyArg_NoArgs(args))
  148.         return NULL;
  149.     Py_BEGIN_ALLOW_THREADS
  150.     pause();
  151.     Py_END_ALLOW_THREADS
  152.     Py_INCREF(Py_None);
  153.     return Py_None;
  154. }
  155. #endif
  156.  
  157. static PyObject *
  158. PySignal_Signal(self, args)
  159.     PyObject *self; /* Not used */
  160.     PyObject *args;
  161. {
  162.     PyObject *obj;
  163.     int sig_num;
  164.     PyObject *old_handler;
  165.     RETSIGTYPE (*func)();
  166.     if (!PyArg_Parse(args, "(iO)", &sig_num, &obj))
  167.         return (PyObject *)NULL;
  168. #ifdef WITH_THREAD
  169.     if (get_thread_ident() != main_thread) {
  170.         PyErr_SetString(PyExc_ValueError,
  171.                 "signal only works in main thread");
  172.         return (PyObject *)NULL;
  173.     }
  174. #endif
  175.     if (sig_num < 1 || sig_num >= NSIG) {
  176.         PyErr_SetString(PyExc_ValueError,
  177.                 "signal number out of range");
  178.         return (PyObject *)NULL;
  179.     }
  180.     if (obj == PySignal_SignalIgnoreHandler)
  181.         func = SIG_IGN;
  182.     else if (obj == PySignal_SignalDefaultHandler)
  183.         func = SIG_DFL;
  184.     else if (!PyCallable_Check(obj)) {
  185.         PyErr_SetString(PyExc_TypeError,
  186. "signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
  187.         return (PyObject *)NULL;
  188.     }
  189.     else
  190.         func = PySignal_Handler;
  191.     if (signal(sig_num, func) == SIG_ERR) {
  192.         PyErr_SetFromErrno(PyExc_RuntimeError);
  193.         return (PyObject *)NULL;
  194.     }
  195.     old_handler = PySignal_SignalHandlerArray[sig_num].func;
  196.     PySignal_SignalHandlerArray[sig_num].tripped = 0;
  197.     Py_INCREF(obj);
  198.     PySignal_SignalHandlerArray[sig_num].func = obj;
  199.     return old_handler;
  200. }
  201.  
  202. static PyObject *
  203. PySignal_GetSignal(self, args)
  204.     PyObject *self; /* Not used */
  205.     PyObject *args;
  206. {
  207.     int sig_num;
  208.     PyObject *old_handler;
  209.     if (!PyArg_Parse(args, "i", &sig_num))
  210.         return (PyObject *)NULL;
  211.     if (sig_num < 1 || sig_num >= NSIG) {
  212.         PyErr_SetString(PyExc_ValueError,
  213.                 "signal number out of range");
  214.         return (PyObject *)NULL;
  215.     }
  216.     old_handler = PySignal_SignalHandlerArray[sig_num].func;
  217.     Py_INCREF(old_handler);
  218.     return old_handler;
  219. }
  220.  
  221.  
  222. /* List of functions defined in the module */
  223.  
  224. static PyMethodDef PySignal_methods[] = {
  225. #ifndef DONT_HAVE_SIG_ALARM
  226.     {"alarm",    PySignal_Alarm},
  227. #endif
  228.     {"signal",    PySignal_Signal},
  229.     {"getsignal",    PySignal_GetSignal},
  230. #ifndef DONT_HAVE_SIG_PAUSE
  231.     {"pause",    PySignal_Pause},
  232. #endif
  233.     {"default_int_handler", PySignal_CDefaultIntHandler},
  234.     {NULL,        NULL}        /* sentinel */
  235. };
  236.  
  237. void
  238. initsignal()
  239. {
  240.     PyObject *m, *d, *x;
  241.     int i;
  242.  
  243. #ifdef WITH_THREAD
  244.     main_thread = get_thread_ident();
  245.     main_pid = getpid();
  246. #endif
  247.  
  248.     /* Create the module and add the functions */
  249.     m = Py_InitModule("signal", PySignal_methods);
  250.  
  251.     /* Add some symbolic constants to the module */
  252.     d = PyModule_GetDict(m);
  253.  
  254.     PySignal_SignalDefaultHandler = PyInt_FromLong((long)SIG_DFL);
  255.     PyDict_SetItemString(d, "SIG_DFL", PySignal_SignalDefaultHandler);
  256.     PySignal_SignalIgnoreHandler = PyInt_FromLong((long)SIG_IGN);
  257.     PyDict_SetItemString(d, "SIG_IGN", PySignal_SignalIgnoreHandler);
  258.     PyDict_SetItemString(d, "NSIG", PyInt_FromLong((long)NSIG));
  259.     PySignal_DefaultIntHandler =
  260.         PyDict_GetItemString(d, "default_int_handler");
  261.  
  262.     PySignal_SignalHandlerArray[0].tripped = 0;
  263.     for (i = 1; i < NSIG; i++) {
  264.         RETSIGTYPE (*t)();
  265.         t = signal(i, SIG_IGN);
  266.         signal(i, t);
  267.         PySignal_SignalHandlerArray[i].tripped = 0;
  268.         if (t == SIG_DFL)
  269.             PySignal_SignalHandlerArray[i].func =
  270.                 PySignal_SignalDefaultHandler;
  271.         else if (t == SIG_IGN)
  272.             PySignal_SignalHandlerArray[i].func =
  273.                 PySignal_SignalIgnoreHandler;
  274.         else
  275.             PySignal_SignalHandlerArray[i].func =
  276.                 Py_None; /* None of our business */
  277.         Py_INCREF(PySignal_SignalHandlerArray[i].func);
  278.     }
  279.     if (PySignal_SignalHandlerArray[SIGINT].func ==
  280.         PySignal_SignalDefaultHandler) {
  281.         /* Install default int handler */
  282.         Py_DECREF(PySignal_SignalHandlerArray[SIGINT].func);
  283.         PySignal_SignalHandlerArray[SIGINT].func =
  284.             PySignal_DefaultIntHandler;
  285.         Py_INCREF(PySignal_DefaultIntHandler);
  286.         signal(SIGINT, &PySignal_Handler);
  287.     }
  288.  
  289. #ifdef SIGHUP
  290.     x = PyInt_FromLong(SIGHUP);
  291.     PyDict_SetItemString(d, "SIGHUP", x);
  292. #endif
  293. #ifdef SIGINT
  294.     x = PyInt_FromLong(SIGINT);
  295.     PyDict_SetItemString(d, "SIGINT", x);
  296. #endif
  297. #ifdef SIGQUIT
  298.     x = PyInt_FromLong(SIGQUIT);
  299.     PyDict_SetItemString(d, "SIGQUIT", x);
  300. #endif
  301. #ifdef SIGILL
  302.     x = PyInt_FromLong(SIGILL);
  303.     PyDict_SetItemString(d, "SIGILL", x);
  304. #endif
  305. #ifdef SIGTRAP
  306.     x = PyInt_FromLong(SIGTRAP);
  307.     PyDict_SetItemString(d, "SIGTRAP", x);
  308. #endif
  309. #ifdef SIGIOT
  310.     x = PyInt_FromLong(SIGIOT);
  311.     PyDict_SetItemString(d, "SIGIOT", x);
  312. #endif
  313. #ifdef SIGABRT
  314.     x = PyInt_FromLong(SIGABRT);
  315.     PyDict_SetItemString(d, "SIGABRT", x);
  316. #endif
  317. #ifdef SIGEMT
  318.     x = PyInt_FromLong(SIGEMT);
  319.     PyDict_SetItemString(d, "SIGEMT", x);
  320. #endif
  321. #ifdef SIGFPE
  322.     x = PyInt_FromLong(SIGFPE);
  323.     PyDict_SetItemString(d, "SIGFPE", x);
  324. #endif
  325. #ifdef SIGKILL
  326.     x = PyInt_FromLong(SIGKILL);
  327.     PyDict_SetItemString(d, "SIGKILL", x);
  328. #endif
  329. #ifdef SIGBUS
  330.     x = PyInt_FromLong(SIGBUS);
  331.     PyDict_SetItemString(d, "SIGBUS", x);
  332. #endif
  333. #ifdef SIGSEGV
  334.     x = PyInt_FromLong(SIGSEGV);
  335.     PyDict_SetItemString(d, "SIGSEGV", x);
  336. #endif
  337. #ifdef SIGSYS
  338.     x = PyInt_FromLong(SIGSYS);
  339.     PyDict_SetItemString(d, "SIGSYS", x);
  340. #endif
  341. #ifdef SIGPIPE
  342.     x = PyInt_FromLong(SIGPIPE);
  343.     PyDict_SetItemString(d, "SIGPIPE", x);
  344. #endif
  345. #ifdef SIGALRM
  346.     x = PyInt_FromLong(SIGALRM);
  347.     PyDict_SetItemString(d, "SIGALRM", x);
  348. #endif
  349. #ifdef SIGTERM
  350.     x = PyInt_FromLong(SIGTERM);
  351.     PyDict_SetItemString(d, "SIGTERM", x);
  352. #endif
  353. #ifdef SIGUSR1
  354.     x = PyInt_FromLong(SIGUSR1);
  355.     PyDict_SetItemString(d, "SIGUSR1", x);
  356. #endif
  357. #ifdef SIGUSR2
  358.     x = PyInt_FromLong(SIGUSR2);
  359.     PyDict_SetItemString(d, "SIGUSR2", x);
  360. #endif
  361. #ifdef SIGCLD
  362.     x = PyInt_FromLong(SIGCLD);
  363.     PyDict_SetItemString(d, "SIGCLD", x);
  364. #endif
  365. #ifdef SIGCHLD
  366.     x = PyInt_FromLong(SIGCHLD);
  367.     PyDict_SetItemString(d, "SIGCHLD", x);
  368. #endif
  369. #ifdef SIGPWR
  370.     x = PyInt_FromLong(SIGPWR);
  371.     PyDict_SetItemString(d, "SIGPWR", x);
  372. #endif
  373. #ifdef SIGIO
  374.     x = PyInt_FromLong(SIGIO);
  375.     PyDict_SetItemString(d, "SIGIO", x);
  376. #endif
  377. #ifdef SIGURG
  378.     x = PyInt_FromLong(SIGURG);
  379.     PyDict_SetItemString(d, "SIGURG", x);
  380. #endif
  381. #ifdef SIGWINCH
  382.     x = PyInt_FromLong(SIGWINCH);
  383.     PyDict_SetItemString(d, "SIGWINCH", x);
  384. #endif
  385. #ifdef SIGPOLL
  386.     x = PyInt_FromLong(SIGPOLL);
  387.     PyDict_SetItemString(d, "SIGPOLL", x);
  388. #endif
  389. #ifdef SIGSTOP
  390.     x = PyInt_FromLong(SIGSTOP);
  391.     PyDict_SetItemString(d, "SIGSTOP", x);
  392. #endif
  393. #ifdef SIGTSTP
  394.     x = PyInt_FromLong(SIGTSTP);
  395.     PyDict_SetItemString(d, "SIGTSTP", x);
  396. #endif
  397. #ifdef SIGCONT
  398.     x = PyInt_FromLong(SIGCONT);
  399.     PyDict_SetItemString(d, "SIGCONT", x);
  400. #endif
  401. #ifdef SIGTTIN
  402.     x = PyInt_FromLong(SIGTTIN);
  403.     PyDict_SetItemString(d, "SIGTTIN", x);
  404. #endif
  405. #ifdef SIGTTOU
  406.     x = PyInt_FromLong(SIGTTOU);
  407.     PyDict_SetItemString(d, "SIGTTOU", x);
  408. #endif
  409. #ifdef SIGVTALRM
  410.     x = PyInt_FromLong(SIGVTALRM);
  411.     PyDict_SetItemString(d, "SIGVTALRM", x);
  412. #endif
  413. #ifdef SIGPROF
  414.     x = PyInt_FromLong(SIGPROF);
  415.     PyDict_SetItemString(d, "SIGPROF", x);
  416. #endif
  417. #ifdef SIGCPU
  418.     x = PyInt_FromLong(SIGCPU);
  419.     PyDict_SetItemString(d, "SIGCPU", x);
  420. #endif
  421. #ifdef SIGFSZ
  422.     x = PyInt_FromLong(SIGFSZ);
  423.     PyDict_SetItemString(d, "SIGFSZ", x);
  424. #endif
  425.     /* Check for errors */
  426.     if (PyErr_Occurred())
  427.         Py_FatalError("can't initialize module signal");
  428. }
  429.  
  430. int
  431. PyErr_CheckSignals()
  432. {
  433.     int i;
  434.     PyObject *f;
  435.     if (!PySignal_IsTripped)
  436.         return 0;
  437. #ifdef WITH_THREAD
  438.     if (get_thread_ident() != main_thread)
  439.         return 0;
  440. #endif
  441.     f = PyEval_GetFrame();
  442.     if (f == (PyObject *)NULL)
  443.         f = Py_None;
  444.     for (i = 1; i < NSIG; i++) {
  445.         if (PySignal_SignalHandlerArray[i].tripped) {
  446.             PyObject *arglist, *result;
  447.             PySignal_SignalHandlerArray[i].tripped = 0;
  448.             arglist = Py_BuildValue("(iO)", i, f);
  449.             if (arglist == (PyObject *)NULL)
  450.                 result = (PyObject *)NULL;
  451.             else {
  452.                 result = PyEval_CallObject(
  453.                  PySignal_SignalHandlerArray[i].func, arglist);
  454.                 Py_DECREF(arglist);
  455.             }
  456.             if (result == (PyObject *)NULL) {
  457.                 return 1;
  458.             } else {
  459.                 Py_DECREF(result);
  460.             }
  461.         }
  462.     }
  463.     PySignal_IsTripped = 0;
  464.     return 0;
  465. }
  466.  
  467. /* Replacement for intrcheck.c functionality */
  468.  
  469. void
  470. PyOS_InitInterrupts ()
  471. {
  472.     initsignal();
  473. }
  474.  
  475. int
  476. PyOS_InterruptOccurred ()
  477. {
  478.     if (PySignal_SignalHandlerArray[SIGINT].tripped) {
  479. #ifdef WITH_THREAD
  480.         if (get_thread_ident() != main_thread)
  481.             return 0;
  482. #endif
  483.         PySignal_SignalHandlerArray[SIGINT].tripped = 0;
  484.         return 1;
  485.     }
  486.     return 0;
  487. }
  488.